home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / hypercrd / xcmds / tffdsply.hqx / tifflzw.c < prev    next >
Text File  |  1993-01-04  |  3KB  |  124 lines

  1. /*
  2.  * This software is copyright 1992 by Robert Morris.
  3.  * You may freely redistribute this software as shareware
  4.  * if you do so in the same form as you got it. If you find
  5.  * this software useful, please send $12 to:
  6.  *   Robert Morris
  7.  *   P.O. Box 1044
  8.  *   Harvard Square Station
  9.  *   Cambridge, MA 02238
  10.  *   ecognome@aol.com
  11.  * If you incorporate any of this software in any kind of
  12.  * commercial product, please send $2 per copy distributed
  13.  * to the above address.
  14.  */
  15.  
  16. #include "tiffinfo.h"
  17.  
  18. /*
  19.  * Lempel-Ziv decompression for TIFF. inlen is the actual number of input
  20.  * characters, and outlen is the number of expected output characters.
  21.  * out[] has size outlen, so it is an error if there are more than outlen
  22.  * characters produced. UnLZW() returns 0 if everything was fine, and
  23.  * < 0 if there was some problem.
  24.  */
  25.  
  26. /*
  27.  * If a code is < 256, it is that character. 256 is the Clear code, and
  28.  * 257 is the end-of-information code. Otherwise it refers to a string
  29.  * previously produced as output, followed by a single character.
  30.  */ 
  31. struct stringtable{
  32.     long index;
  33.     long len;
  34. };
  35. #define ClearCode 256
  36. #define EndOfInformation 257
  37.  
  38. void
  39. ClearTable(struct stringtable *table)
  40. {
  41.     int i;
  42.     
  43.     for(i = 0; i < 256; i++){
  44.         table[i].index = 0;
  45.         table[i].len = 0;
  46.     }
  47. }
  48.  
  49. int
  50. UnLZW(char *in, long inlen, char *out, long outlen)
  51. {
  52.     struct stringtable *table = 0;
  53.     int ncodes; /* # of codes in the table */
  54.     int codelen; /* current code length in bits */
  55.     unsigned short *ip; /* current point in input */
  56.     int bit; /* # of (high) bits consumed in *ip */
  57.     char *op; /* next element to write in out[] */
  58.     unsigned short code;
  59.     int i;
  60.     
  61.     table = (struct stringtable *) NewPtr(sizeof(struct stringtable) * 4096);
  62.     if(table == 0)
  63.         return(MemError());
  64.         
  65.     ClearTable(table);
  66.     ncodes = 258; /* one for each 8-bit character, plus two special codes */
  67.     codelen = 9;
  68.     
  69.     op = out;
  70.     ip = (unsigned short *) in;
  71.     bit = 0;
  72.     
  73.     while(1){
  74.         if((char *)ip >= in + inlen){
  75.             /* ran out of information before we saw EndOfInformation! */
  76.             goto bad;
  77.         }
  78.         
  79.         if(bit >= 16){
  80.             ip++;
  81.             bit = 0;
  82.         }
  83.         code = (*ip << bit) >> (16 - codelen);
  84.         bit += codelen;
  85.         if(bit > 16){
  86.             /* need to read some more */
  87.             ip++;
  88.             bit -= 16;
  89.             code |= (*ip >> (16 - bit));
  90.         }
  91.         
  92.         if(code == ClearCode){
  93.             ncodes = 258;
  94.             codelen = 9;
  95.         } else if(code == EndOfInformation){
  96.             break;
  97.         } else if(code < ncodes){
  98.             if(op + table[code].len > out + outlen)
  99.                 goto bad;
  100.             table[ncodes].index = op - out;
  101.             if(code < 256){
  102.                 *op++ = code;
  103.                 table[ncodes].len = 2;
  104.             } else {
  105.                 for(i = 0; i < table[code].len; i++)
  106.                     *op++ = out[table[code].index + i];
  107.                 table[ncodes].len = table[code].len + 1;
  108.             }
  109.             ncodes++;
  110.             if(ncodes == (1 << codelen))
  111.                 codelen++;
  112.         } else {
  113.             /* code out of range */
  114.             goto bad;
  115.         }
  116.     }
  117.     
  118.     DisposPtr(table);
  119.     return(0);
  120. bad:
  121.     if(table)
  122.         DisposPtr(table);
  123.     return(-1);
  124. }